iT邦幫忙

2021 iThome 鐵人賽

DAY 13
0
自我挑戰組

ASP.NET Core & Blazor系列 第 13

Day 13 EventCallback, event from child to parent

  • 分享至 

  • xImage
  •  

目前的4篇日誌是來自我們寫好的假資料,但正常來說不會這樣做,而是有顆按鈕讓使用者按了之後,增加或減少日誌的數量。

增加的按鈕會放在<Blog>,按了「增加」按鈕產生一筆新的Post供使用者輸入,再讓使用者點擊「確認」按鈕儲存日誌。

刪除的按鈕則可以放在<Blog>,再於<Post>加入checkbox,讓使用者自己勾選要刪除哪些Post;或是放在<Post>,按下刪除按鈕就刪除該筆日誌。

新增按鈕很簡單,只要在<MyButton>加上@onclick事件即可,開始之前,先將版面稍作修改,順便把FontSizeStyle移除。
https://ithelp.ithome.com.tw/upload/images/20210913/20140893CVp4F1ZHDT.png

C#部分則加入add()方法,原本loadData()的日誌刪除。
https://ithelp.ithome.com.tw/upload/images/20210913/20140893bgDJUO9J07.png

接著點擊Add按鈕,就可以看到日誌筆數增加了。
https://ithelp.ithome.com.tw/upload/images/20210913/20140893EAHk5gYd1Q.png

接著來做Delete功能,在Post.razor加入Delete按鈕。
https://ithelp.ithome.com.tw/upload/images/20210913/20140893uG4L3oQToH.png

但問題來了,當我按下Delete按鈕,<Blog>怎麼知道我刪除的是哪一筆Post?這時候就需要PostId可以識別,於是加入一個私有變數postId,每次按下add()都+1,正常來說PostId會跟著Post而不是由Blog產生,不過因為還沒接觸到資料庫,所以先這樣將就,未來連接資料庫後就會改變。
https://ithelp.ithome.com.tw/upload/images/20210913/20140893IRFOXRAI8w.png

為了驗證是否正確,刪除原本Post.razor註解的Post.Id,加入新樣式的Post.PostId,可以看到沒有問題。
https://ithelp.ithome.com.tw/upload/images/20210913/20140893Oz8ro70HYN.pnghttps://ithelp.ithome.com.tw/upload/images/20210913/20140893zDMASGcHrv.png

現在有了識別PostId,又產生了新問題,要怎麼讓<Blog>收到PostId?目前PostId由<Blog>產生,所以沒這問題,等未來PostId由資料庫產生後,<Blog>就不會知道PostId了。前面說的都是從Parent component傳遞資料到Child component的方法,我們現在要從Child component傳資料到Parent component,有辦法做到反向傳回去嗎?

有的,那就是EventCallback,但是要把Delete改成<input>而非<MyButton>,因為EventCallback是由Child傳向Parent,如果用<MyButton>,PostId的流向就必須先這樣 <Blog>=><Post>=><MyButton>,接著再用EventCallback反向<MyButton>=><Post>=><Blog>,實在太麻煩了。

先把Delete按鈕改成<input>,加入@onclick="returnPostId"
https://ithelp.ithome.com.tw/upload/images/20210913/20140893yf7sf58W6T.png

接著在Post.razor.cs定義型別為EventCallback<int>的Property getPostId,記住一定要加上[Parameter]attribute,因為這要讓<Blog>呼叫。然後完整定義returnPostId()方法,裡面做的就是getPostId.InvokeAsync(Post.PostId);,當外部傳來的getPostId被觸發時,就將Post.PostId傳給Parent也就是<Blog>
https://ithelp.ithome.com.tw/upload/images/20210913/20140893pNF04gyVwb.png

再於Blog.razor.cs定義同名方法getPostId(int id),名字不需要一樣,這邊只是為了方便取同名,裡面做的事情就是移除跟收到的PostId有相同值的Post。
https://ithelp.ithome.com.tw/upload/images/20210913/20140893Pi8BCv8aDl.png

最後在Blog.razor<Post>getPostId放入剛剛定義的方法就可以了。
https://ithelp.ithome.com.tw/upload/images/20210913/20140893ssZP34Vamv.png

我們來實驗看看,先新增4筆日誌,再刪除第2筆,可以看到Post Id等於2的那筆成功被刪除了。https://ithelp.ithome.com.tw/upload/images/20210913/201408931xx9cdTwAF.pnghttps://ithelp.ithome.com.tw/upload/images/20210913/201408931QcO0xJanA.png

除了EventCallback,還有Delegate可以使用,不過侷限性較大,我們也來試試看。

先在Post.razor.cs定義型別為Action<int>的Property getPostIdForDelegatereturnPostId()改用getPostIdForDelegate
https://ithelp.ithome.com.tw/upload/images/20210913/20140893ZBiVqfeGZK.png

接著在Blog.razor<Post>改用getPostIdForDelegate
https://ithelp.ithome.com.tw/upload/images/20210913/20140893ATOhIyigrb.png

但是真的點擊後會發現不會刪除日誌,這是因為EventCallback會監控Component,一旦有異動就會重新render,Delegate則不會,Delegate必須在Parent component也就是Blog.razor.cs呼叫StateHasChanged();方法,讓Parent component知道狀態改變了。
https://ithelp.ithome.com.tw/upload/images/20210913/20140893VUpQ1GHnV9.png

另外Delegate一旦在Child component定義了,Parent component就必須要叫用,否則會發生錯誤,EventCallback則沒這問題。
https://ithelp.ithome.com.tw/upload/images/20210913/201408932t4FdnHeWA.png

Ref: Blazor EventCallback

Ref: EventCallback

Ref: Blazor Tutorial - Ep11 - EventCallback and how it is different from delegate


上一篇
Day 12 Cascading values and parameters
下一篇
Day 14 JavaScript interop
系列文
ASP.NET Core & Blazor30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言